package com.msmall.community.weather.model;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class WeatherPaser {

	private static final String DEFAULT_URL = "http://www.google.com/";
	
	public static final String ERRORS = "//xml_api_reply/weather/problem_cause";
	public static final String CITY = "//xml_api_reply/weather/forecast_information/city";
	public static final String POSTAL_CODE = "//xml_api_reply/weather/forecast_information/postal_code";
	public static final String LATITUDE_E6 = "//xml_api_reply/weather/forecast_information/latitude_e6";
	public static final String LONGITUDE_E6 = "//xml_api_reply/weather/forecast_information/longitude_e6";
	public static final String FORECAST_DATE = "//xml_api_reply/weather/forecast_information/forecast_date";
	public static final String CURRENT_DATE_TIME = "//xml_api_reply/weather/forecast_information/current_date_time";
	public static final String UNIT_SYSTEM = "//xml_api_reply/weather/forecast_information/unit_system";
	public static final String CURRENT_CONDITION = "//xml_api_reply/weather/current_conditions/condition";
	public static final String CURRENT_TEMP_F = "//xml_api_reply/weather/current_conditions/temp_f";
	public static final String CURRENT_TEMP_C = "//xml_api_reply/weather/current_conditions/temp_c";
	public static final String CURRENT_HUMIDITY = "//xml_api_reply/weather/current_conditions/humidity";
	public static final String CURRENT_ICON = "//xml_api_reply/weather/current_conditions/icon";
	public static final String CURRENT_WIND_CONDITION = "//xml_api_reply/weather/current_conditions/wind_condition";
	public static final String FORECAST = "//xml_api_reply/weather/forecast_conditions";
	public static final String FORECAST_DAY_OF_WEEK = "day_of_week";
	public static final String FORECAST_LOW = "low";
	public static final String FORECAST_HIGH = "high";
	public static final String FORECAST_ICON = "icon";
	public static final String FORECAST_CONDITION = "condition";
	
	public static final String WEEK_0 = "周日";
	public static final String WEEK_1 = "周一";
	public static final String WEEK_2 = "周二";
	public static final String WEEK_3 = "周三";
	public static final String WEEK_4 = "周四";
	public static final String WEEK_5 = "周五";
	public static final String WEEK_6 = "周六";
	
	public static Weather parser(String info) throws Exception{
		Weather weather = new Weather();
		SAXReader xmlReader = new SAXReader();
        xmlReader.setEncoding("UTF-8");
        try {
			Element root = xmlReader.read(new ByteArrayInputStream(info.getBytes("UTF-8"))).getRootElement();
			checkErrors(root);
			setCity(root, weather);
			setPostalCode(root, weather);
			setLatitudeE6(root, weather);
			setLongitudeE6(root, weather);
			setDate(root, weather);
			setCurrentDateTime(root, weather);
			setCondition(root, weather);
			setTempf(root, weather);
			setTempc(root, weather);
			setHumidity(root, weather);
			setIcon(root, weather);
			setWindCondition(root, weather);
			setForecasts(root, weather);
			return weather;
		} catch (DocumentException e) {
			throw e;
		} catch (UnsupportedEncodingException e) {
			throw e;
		} catch (Exception e) {
			throw e;
		}
	}
	
	public static void checkErrors(Element root) throws Exception{
		try{
			Element city = (Element) root.selectSingleNode(ERRORS);
			if(city != null){
				throw new Exception("City not found");
			}
		}catch(Exception e){
			throw e;
		}
	}
	
	public static void setCity(Element root, Weather weather) throws Exception{
		try{
			Element city = (Element) root.selectSingleNode(CITY);
			String citys = city.attributeValue("data");
			String cityp = citys;
			String cityf = "";
			int index = citys.indexOf(",");
			if(index != -1){
				cityp = citys.substring(0, index);
				cityf = citys.substring(index+1);
			}
			weather.setCity(cityp);
			weather.setProvince(cityf);
			
		}catch(Exception e){
			throw e;
		}
	}
	public static void setPostalCode(Element root, Weather weather) throws Exception{
		try{
			Element postalCode = (Element) root.selectSingleNode(POSTAL_CODE);
			String PostalCodes = postalCode.attributeValue("data"); 
			weather.setPostalCode(PostalCodes);
		}catch(Exception e){
			throw e;
		}
	}
	public static void setLatitudeE6(Element root, Weather weather) throws Exception{
		try{
			Element latitudeE6 = (Element) root.selectSingleNode(LATITUDE_E6);
			String latitudeE6s = latitudeE6.attributeValue("data"); 
			weather.setLatitude(latitudeE6s);
		}catch(Exception e){
			throw e;
		}
	}
	public static void setLongitudeE6(Element root, Weather weather) throws Exception{
		try{
			Element longitudeE6 = (Element) root.selectSingleNode(LONGITUDE_E6);
			String longitudeE6s = longitudeE6.attributeValue("data"); 
			weather.setLongitude(longitudeE6s);
		}catch(Exception e){
			throw e;
		}
	}
	public static void setDate(Element root, Weather weather) throws Exception{
		try{
			Element date = (Element) root.selectSingleNode(FORECAST_DATE);
			String dates = date.attributeValue("data");
			SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
			Date datex = format.parse(dates);
			weather.setDate(datex);
		}catch(Exception e){
			throw e;
		}
	}
	
	public static void setCurrentDateTime(Element root, Weather weather) throws Exception{
		try{
			Element date = (Element) root.selectSingleNode(CURRENT_DATE_TIME);
			String dates = date.attributeValue("data");
			SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
			format.setTimeZone(TimeZone.getTimeZone("GMT +0800"));
			Date datex = format.parse(dates);
			weather.setCurrentDateTime(datex);
		}catch(Exception e){
			throw e;
		}
	}
	
	public static void setCondition(Element root, Weather weather) throws Exception{
		try{
			Element condition = (Element) root.selectSingleNode(CURRENT_CONDITION);
			String conditions = condition.attributeValue("data"); 
			weather.setCondition(conditions);
		}catch(Exception e){
			throw e;
		}
	}
	public static void setTempf(Element root, Weather weather) throws Exception{
		try{
			Element tempf = (Element) root.selectSingleNode(CURRENT_TEMP_F);
			String tempfs = tempf.attributeValue("data"); 
			weather.setTempf(tempfs);
		}catch(Exception e){
			throw e;
		}
	}
	public static void setTempc(Element root, Weather weather) throws Exception{
		try{
			Element tempc = (Element) root.selectSingleNode(CURRENT_TEMP_C);
			String tempcs = tempc.attributeValue("data"); 
			weather.setTempc(tempcs);
		}catch(Exception e){
			throw e;
		}
	}
	public static void setHumidity(Element root, Weather weather) throws Exception{
		try{
			Element humidity = (Element) root.selectSingleNode(CURRENT_HUMIDITY);
			String humiditys = humidity.attributeValue("data"); 
			weather.setHumidity(format(humiditys));
		}catch(Exception e){
			throw e;
		}
	}
	public static void setIcon(Element root, Weather weather) throws Exception{
		try{
			Element icon = (Element) root.selectSingleNode(CURRENT_ICON);
			String icons = icon.attributeValue("data"); 
			if(icons.startsWith("/"))
				icons = icons.substring(1, icons.length());
			weather.setIcon(DEFAULT_URL + icons);
		}catch(Exception e){
			throw e;
		}
	}
	public static void setWindCondition(Element root, Weather weather) throws Exception{
		try{
			Element windCondition = (Element) root.selectSingleNode(CURRENT_WIND_CONDITION);
			String windConditions = windCondition.attributeValue("data"); 
			
			weather.setWindCondition(format(windConditions));
		}catch(Exception e){
			throw e;
		}
	}
	public static void setForecasts(Element root, Weather weather)throws Exception{
		try{
			List<Element> list = root.selectNodes(FORECAST);
			if(list == null || list.size() <= 0)
				return ;
			for(int i = 0; i < list.size(); i ++){
				setForecast(list.get(i), weather);
			}
		}catch(Exception e){
			throw e;
		}
	}
	public static void setForecast(Element root, Weather weather)throws Exception{
		try{
			ForeCast foreCast = new ForeCast();
			
			Element week = (Element) root.element(FORECAST_DAY_OF_WEEK);
			String weeks = week.attributeValue("data");
			Date today = getDate(weather.getDate(), weeks);
			foreCast.setDate(today);
			
			foreCast.setWeek(weeks);
			Element low = (Element) root.element(FORECAST_LOW);
			String lows = low.attributeValue("data"); 
			foreCast.setLow(lows);
			Element high = (Element) root.element(FORECAST_HIGH);
			String highs = high.attributeValue("data"); 
			foreCast.setHigh(highs);
			Element icon = (Element) root.element(FORECAST_ICON);
			String icons = icon.attributeValue("data"); 
			if(icons.startsWith("/"))
				icons = icons.substring(1, icons.length());
			foreCast.setIcon(DEFAULT_URL + icons);
			Element condition = (Element) root.element(FORECAST_CONDITION);
			String conditions = condition.attributeValue("data"); 
			foreCast.setCondition(conditions);
			weather.addForecast(foreCast);
		}catch(Exception e){
			throw e;
		}
	}
	
	/**
	 * 去掉空格，并将符号转为全角
	 * @return
	 */
	private static String format(String o){
		final String s1 = " ";
		final String s2 = "、";
		final String s3 = "：";
		final String s4 = "/";
		o = o.replaceAll(s1, "").replaceAll(s2, "、").replaceAll(s3, "：").replaceAll(s4, "／");
		return o;
	}
	
	private static Date getDate(Date today, String week){
		Calendar c = Calendar.getInstance();
		c.setTime(today);
		int i = c.get(Calendar.DAY_OF_WEEK) - 1;//0是星期日，1-6分别是星期一-六
		int the = 0;
		if(WEEK_0.equals(week)){
			the = 0;
		}
		if(WEEK_1.equals(week)){
			the = 1;
		}
		if(WEEK_2.equals(week)){
			the = 2;
		}
		if(WEEK_3.equals(week)){
			the = 3;
		}
		if(WEEK_4.equals(week)){
			the = 4;
		}
		if(WEEK_5.equals(week)){
			the = 5;
		}
		if(WEEK_6.equals(week)){
			the = 6;
		}
		int cha = the - i;
		if(cha < 0) cha+=7;
		c.add(Calendar.DAY_OF_WEEK, cha);
		return c.getTime();
	}
}
